package reflection;

import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Properties;

/**
 * @program: javase
 * @description:
 * @author: lld
 * @create: 2020-11-22 16:25
 **/
public class Test1 {
    @Test
    public void test1() throws Exception {
        //通过反射创建对象
        Class<Reflect1> clazz = Reflect1.class;
        Constructor<Reflect1> constructor = clazz.getConstructor(String.class, int.class);
        Reflect1 tom = constructor.newInstance("tom", 12);
//        Reflect1 tom = clazz.newInstance();//无参
        System.out.println(tom);
        //通过反射调用公用属性
        Field id = clazz.getDeclaredField("id");
        id.set(tom, 21);
        System.out.println(tom);

        //通过反射调用私有属性
        Field age = clazz.getDeclaredField("age");
        age.setAccessible(true);//设置私有可访问
        age.set(tom, 211);
        System.out.println(tom);
        //通过反射调用公用方法
        Method show = clazz.getDeclaredMethod("show");
        show.invoke(tom);
        //通过反射调用私有方法
        Method show1 = clazz.getDeclaredMethod("show1", int.class);
        show1.setAccessible(true);
        Object invoke = show1.invoke(tom, 23);//执行
        System.out.println((String) invoke);//方法返回值
        //通过反射调用静态方法
        Method staticM = clazz.getDeclaredMethod("staticMethod");
        staticM.setAccessible(true);
        Object invoke1 = staticM.invoke(Test1.class);//执行
        System.out.println(invoke1);//无返回值时返回null

    }

    /*
    类的加载过程：
    .java文件编译成.class文件，.class运行
    相当于将该字节码文件加载到内存中，此过程称为类的加载
    Class实例=运行时的类
     */
//获取 Class实例方式
    @Test
    public void test2() throws Exception {
        //1类的属性Reflect1.class
        Class<Reflect1> clazz1 = Reflect1.class;
        System.out.println(clazz1);
        //2类的对象.getClass();
        Reflect1 reflect1 = new Reflect1();
        Class<? extends Reflect1> clazz2 = reflect1.getClass();
        System.out.println(clazz2);
        //3Class.forName()
        Class<?> clazz3 = Class.forName("reflection.Reflect1");
        System.out.println(clazz3);
//获取的都是同一个Class实例
        System.out.println(clazz1 == clazz2);
        System.out.println(clazz3 == clazz2);
    }

    @Test
    public void test3() throws Exception {
        //读取配置文件
        Properties prop = new Properties();
        ClassLoader classLoader = Test1.class.getClassLoader();
        InputStream resourceAsStream = classLoader.getResourceAsStream("reflection/jdbc.properties");
        prop.load(resourceAsStream);
        String name = prop.getProperty("name");
        System.out.println(name);
    }

    @Test
    public void test4() throws Exception {
//        Class<Reflect1> clazz = Reflect1.class;
        Class clazz = Class.forName("reflection.Reflect1");
        //调用空参构造器
        Reflect1 reflect1 = (Reflect1) clazz.newInstance();
        System.out.println(reflect1);
        //获取属性,只能获取public权限的属性
        Field[] fields = clazz.getFields();
        System.out.println(Arrays.toString(fields));
        //获取类实现的接口
        Class[] interfaces = clazz.getInterfaces();
        System.out.println(Arrays.toString(interfaces));
        //获取注解
        Annotation[] annotations = clazz.getAnnotations();
        System.out.println(Arrays.toString(annotations));

    }
   @Test
    public void test5() throws Exception {
        /**找字节码文件,加载类，创建反射对象 */
        Class clazz = Class.forName("reflection.Reflect1");
       /** 在使用反射对象时，才加载静态变量，静态代码块 */
        Class<Reflect1> clazz1 = Reflect1.class;
       Reflect1 reflect1 = clazz1.newInstance();
       System.out.println(clazz1);



       Class<?> aClass = ClassLoader.getSystemClassLoader().loadClass("java.util.Date");
       Date o = (Date) aClass.newInstance();
       SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       String format1 = format.format(o);
       System.out.println(format1);
       Date date = format.parse(format1);
       System.out.println(date);
   }

}
